﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using DSPL.DataAccess;
using System.Windows;
using System.Windows.Forms;
using System.Data.SqlClient;
using DSPL.Contracts;
using DSPL.Contracts.Common;

namespace DSPL.Services.Rules
{
    public class StockRulesService
    {
        // Stock balance FIFO
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dtStockTable">Temporary table - Items Data Table</param>
        /// <param name="dtLocationTable">Temporary table - Location Data Table</param>
        /// <param name="fromDate">From Date</param>
        /// <param name="toDate">To Date</param>
        /// <param name="dtStockBalFifo"></param>
        /// <param name="transactionType">Transaction Types</param>
        /// <param name="dispatchType">Dispatch Types</param>
        /// <param name="reportTableGroup"></param>
        /// <param name="originalItemsTable"></param>
        /// <param name="originalStockIn">Original Stock In Table - fStkIn</param>
        /// <returns>Creates a temporary cursor TmpStockFifo in the database which need to be destroyed in the calling method.</returns>
        public bool StockBalanceFifo(DataTable dtStockTable, DataTable dtLocationTable, DateTime fromDate, DateTime toDate, out DataTable dtStockBalFifo,
            string transactionType = "", string dispatchType = "", string reportTableGroup = "", string originalItemsTable = "", string originalStockIn = "")
        {

            dtStockBalFifo = new DataTable();
            if (dtStockTable == null || dtStockTable.Rows.Count == 0)
            {
                return false;
            }

            if (dtLocationTable == null || dtLocationTable.Rows.Count == 0)
            {
                return false;
            }

            if (fromDate == null)
            {
                return false;
            }

            bool isOpenCal = false;
            if (toDate == null)
            {
                toDate = fromDate;
            }
            else
            {
                isOpenCal = true;
            }

            DateTime openFromDate;
            if (isOpenCal)
            {
                openFromDate = fromDate;
            }
            else
            {
                openFromDate = Convert.ToDateTime("1/1/1900");
            }

            bool isSuccess = true;
           
            var  db = DatabaseAccess.Instance;
            List<ParameterWithValue> paramList = new List<ParameterWithValue>();
            paramList.Add(new ParameterWithValue("@tableItems", dtStockTable));
            paramList.Add(new ParameterWithValue("@tableLocations", dtLocationTable));
            paramList.Add(new ParameterWithValue("@dateFrom", fromDate));
            paramList.Add(new ParameterWithValue("@dateTo", toDate));
            paramList.Add(new ParameterWithValue("@dateOpenFrom", openFromDate));            
            paramList.Add(new ParameterWithValue("@vchTransactionType", transactionType));
            paramList.Add(new ParameterWithValue("@vchDispatchType", dispatchType));
            paramList.Add(new ParameterWithValue("@vchReportGroup", reportTableGroup));
            paramList.Add(new ParameterWithValue("@vchItemTable", originalItemsTable));
          //  paramList.Add(new ParameterWithValue("@vchStockInTable", originalStockIn));

            //  paramList.Add(new ParameterWithValue("@tableStockBalFifo",dtStockBalFifo,, ParameterDirection.InputOutput));
            //paramList.Add(new ParameterWithValue("@result", true, SqlDbType.Structured, ParameterDirection.InputOutput));
            paramList.Add(new ParameterWithValue("@ReturnValue", 0, SqlDbType.Bit, ParameterDirection.Output));
            SpCaller spCaller = new SpCaller() { SpName = "stock.STOCK_BALANCE_FIFO", SpParamValues = paramList.ToArray() };
            if (db.Excecute(spCaller, "@ReturnValue") == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

      
        // FiFo_In_Stk_Upd
         #region Fifo_In_Stk_Upd

        // Multiple Line FIFO Stock Receive and QOH Update 
        /// <summary>
        /// Update Backend Location Stock Balance table and insert record to FIFO Receive table.
        /// </summary>
        /// <param name="stockInHandTable">Location wise stock In hand table (fItemsLoc)</param>
        /// <param name="stockReceiveTable">FIFO Receive table (fStkIn)</param>
        /// <param name="dtTranDet">Transaction Detail table - temporary table</param>
        /// <param name="transactionDate">Transaction Date</param>
        /// <param name="referenceNo">Transaction Reference No</param>
        /// <param name="locCode">Location Code </param>
        /// <param name="tranactionType">Transaction Type</param> 
        /// <param name="productMasterTable">Product Master Table</param>
        /// <param name="TransactionDetailTable">Original Transaction Detail Table</param>
        /// <param name="isAverageUpdate">Average Update Flag (true – Update, false – Omit)</param>
        /// <param name="linkRefernceNo">Link Transaction Reference (Po reference no in GRN)</param>
        /// <param name="linkTranactionDetailTable">Link Transaction Detail Table</param> 
        /// <returns></returns>
        public bool MultipleFifoStockReceive(string stockInHandTable, string stockReceiveTable, string transactionDetailTableName,int primaryKey, DateTime transactionDate,
            string referenceNo, int locationPk, string tranactionType, string productMasterTable, ref SqlTransaction sqlTransaction,
            bool isAverageUpdate = false, string linkRefernceNo = "", string linkTranactionDetailTable = "")
        {            
            if (stockInHandTable == String.Empty)
            {               
                return false;
            }

            if (stockReceiveTable == String.Empty)
            {
               return false;
            }

            if (transactionDetailTableName == string.Empty) 
            {                
                return false;
            }
            if (primaryKey==0)
            {
                return false;
            }

            if (referenceNo == String.Empty)
            {               
                return false;
            }

            if (locationPk == 0)
            {                
                return false;
            }

            if (tranactionType == String.Empty)
            {                
                return false;
            }

            if (isAverageUpdate)
            {
                if (productMasterTable == string.Empty)
                {                    
                    return false;
                }
            }

            if (linkRefernceNo != string.Empty && linkTranactionDetailTable == string.Empty)
            {
                return false;
            }


            var db = DatabaseAccess.Instance;
            List<ParameterWithValue> paramList = new List<ParameterWithValue>();
            paramList.Add(new ParameterWithValue("@stockInHandTable", stockInHandTable));
            paramList.Add(new ParameterWithValue("@stockReceiveTable", stockReceiveTable));
            paramList.Add(new ParameterWithValue("@transactionDetailTable", transactionDetailTableName));
            paramList.Add(new ParameterWithValue("@primaryKey", primaryKey));
            paramList.Add(new ParameterWithValue("@transactionDate", transactionDate));
            paramList.Add(new ParameterWithValue("@locationPk", locationPk));

            paramList.Add(new ParameterWithValue("@tranactionType", tranactionType));
            paramList.Add(new ParameterWithValue("@productMasterTable", productMasterTable));
            paramList.Add(new ParameterWithValue("@linkRefernceNo", linkRefernceNo));
            paramList.Add(new ParameterWithValue("@linkTranactionDetailTable", linkTranactionDetailTable));
           
            //  paramList.Add(new ParameterWithValue("@tableStockBalFifo",dtStockBalFifo,, ParameterDirection.InputOutput));
            //paramList.Add(new ParameterWithValue("@result", true, SqlDbType.Structured, ParameterDirection.InputOutput));
            paramList.Add(new ParameterWithValue("@ReturnValue", 0, SqlDbType.Bit, ParameterDirection.Output));
            SpCaller spCaller = new SpCaller() { SpName = "stock.FIFO_STOCK_IN_UPDATE", SpParamValues = paramList.ToArray() };
            if (db.Excecute(spCaller, "@ReturnValue",ref  sqlTransaction) == null)
            {
                return false;
            }
            else
            {
                return true;
            }

            bool isSuccess = true;
            return isSuccess;

        }

          #endregion

        /// <summary>
        /// Validates Stock Transaction Date
        /// </summary>
        /// <param name="transactionDate"> Transaction Date</param>
        /// <param name="referenceNo">Reference No</param>
        /// <param name="checkBackDated">whether to check back dates transactions or not i.e. true or false</param>
        /// <param name="reportGroup">Report Group Name</param>
        /// <returns>true or false. Updates the errorList if any error occurs</returns>
        public bool ValidateStockTransactionDate(DateTime transactionDate, string referenceNo = "", bool checkBackDated = false, string reportGroup = "")
        {

            if (transactionDate == null)
            {
                return false;
            }

            var db = DatabaseAccess.Instance;
            bool isSuccess=true ;
           
            List<ParameterWithValue> paramList = new List<ParameterWithValue>();

            paramList.Add(new ParameterWithValue("@dateTransaction", transactionDate));
            paramList.Add(new ParameterWithValue("@vchReferenceNo", referenceNo));
            paramList.Add(new ParameterWithValue("@isCheckBackDated", checkBackDated));
            paramList.Add(new ParameterWithValue("@vchReportGroup", reportGroup));
            paramList.Add(new ParameterWithValue("@result", 1, SqlDbType.Int , ParameterDirection.Output));
            paramList.Add(new ParameterWithValue("@message","", SqlDbType.VarChar , ParameterDirection.Output,5000));           
            
            SpCaller spCaller = new SpCaller() { SpName = "Stock.VALIDATE_STOCK_TXNDATE", SpParamValues = paramList.ToArray() };

            Dictionary<string,object> result = (Dictionary<string,object>)(db.ExcecuteMultipleOutputParameters(spCaller));

            foreach (KeyValuePair<string, object> outputParam in result)
            {
                if (outputParam.Key == "@result")
                {
                    if ((int)outputParam.Value == 1)
                    {
                        break;
                    }                    

                }
                if (outputParam.Key == "@message")
                {
                    if (outputParam.Value.ToString() != string.Empty)
                    {
                        MessageBox.Show(outputParam.Value.ToString(), "Stock Rules", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        isSuccess = false;
                    }

                }
            }
            
            return isSuccess;            

        }

         #region Fifo_In_Stk_Upd

        // Multiple Line FIFO Stock Receive and QOH Update 
        /// <summary>
        /// Update Backend Location Stock Balance table and insert record to FIFO Receive table.
        /// </summary>
        /// <param name="stockInHandTable">Location wise stock In hand table (fItemsLoc)</param>
        /// <param name="stockReceiveTable">FIFO Receive table (fStkIn)</param>
        /// <param name="dtTranDet">Transaction Detail table - temporary table</param>
        /// <param name="transactionDate">Transaction Date</param>
        /// <param name="referenceNo">Transaction Reference No</param>
        /// <param name="locCode">Location Code </param>
        /// <param name="tranactionType">Transaction Type</param> 
        /// <param name="productMasterTable">Product Master Table</param>
        /// <param name="TransactionDetailTable">Original Transaction Detail Table</param>
        /// <param name="isAverageUpdate">Average Update Flag (true – Update, false – Omit)</param>
        /// <param name="linkRefernceNo">Link Transaction Reference (Po reference no in GRN)</param>
        /// <param name="linkTranactionDetailTable">Link Transaction Detail Table</param> 
        /// <returns></returns>
        public bool MultipleFifoStockReceive(string stockInHandTable, string stockReceiveTable, DataTable dtTranDet, DateTime transactionDate,
            string referenceNo, string locCode, string tranactionType, string productMasterTable,
            bool isAverageUpdate = false, string linkRefernceNo = "", string linkTranactionDetailTable = "", string TransactionDetailTable = "", SqlTransaction sqlTransaction = null)
        {

            if (stockInHandTable == String.Empty)
            {
                return false;
            }

            if (stockReceiveTable == String.Empty)
            {
                return false;
            }

            if ((dtTranDet == null) || (dtTranDet.Rows.Count == 0))
            {
                return false;
            }

            if (referenceNo == String.Empty)
            {
                return false;
            }

            if (locCode == String.Empty)
            {
                return false;
            }

            if (tranactionType == String.Empty)
            {
                return false;
            }

            if (isAverageUpdate)
            {
                if (productMasterTable == string.Empty)
                {
                    return false;
                }
            }

            if (linkRefernceNo != string.Empty && linkTranactionDetailTable == string.Empty)
            {
                return false;
            }


            var avgPriceDecimalPoints = Convert.ToInt32(GlobalVariables.AverageRateDecimalPoints);
            
            List<ParameterWithValue> paramList = new List<ParameterWithValue>();

            paramList.Add(new ParameterWithValue("@dateTransaction", transactionDate));
            paramList.Add(new ParameterWithValue("@vchReferenceNo", referenceNo));           
            paramList.Add(new ParameterWithValue("@result", 1, SqlDbType.Int, ParameterDirection.Output));
            paramList.Add(new ParameterWithValue("@message", "", SqlDbType.VarChar, ParameterDirection.Output, 5000));

            SpCaller spCaller = new SpCaller() { SpName = "stock.FIFO_IN_STOCK_UPDATE", SpParamValues = paramList.ToArray() };


            return true;
        }
 #endregion

    }

    public class TestStockRules
    {
        public void TestRules()
        {
            var _databaseAccess = DatabaseAccess.Instance;

            DateTime txnDate = new DateTime(2014, 12, 23);
            DSPL.Services.Rules.StockRulesService stkRules = new DSPL.Services.Rules.StockRulesService();
            bool isSuccess = false;
            //isSuccess = stkRules.ValidateStockTransactionDate(transactionDate: txnDate, checkBackDated: true);
            //MessageBox.Show(isSuccess.ToString());

            DataTable dtItems = new DataTable();
            DataTable dtLocations = new DataTable();


            List<ColumnWithValue> columnList = new List<ColumnWithValue>();
            columnList.Add(new ColumnWithValue() { ColumnName = "ItemPk" });
            columnList.Add(new ColumnWithValue() { ColumnName = "ItemCode" });
            columnList.Add(new ColumnWithValue() { ColumnName = "ItemName" });

            Query query = new Query() { TableName = "fItems", QType = QueryType.SELECT, ColValues = columnList.ToArray() };
            dtItems = (_databaseAccess.ExcecuteSelect(query));

            List<ColumnWithValue> columnList1 = new List<ColumnWithValue>();
            columnList1.Add(new ColumnWithValue() { ColumnName = "LocationPk"});
            columnList1.Add(new ColumnWithValue() { ColumnName = "LocCode"});
            columnList1.Add(new ColumnWithValue() { ColumnName = "LocName"});

            Query query1 = new Query() { TableName = "fLocation", QType = QueryType.SELECT, ColValues = columnList1.ToArray() };
            dtLocations = (_databaseAccess.ExcecuteSelect(query1));

            DateTime dtTo = DateTime.Now;
           // DateTime dtTo = new DateTime(2013, 12, 26);
            DateTime dtFrom = new DateTime(1900, 1, 1);
            DataTable dtStockBal = new DataTable();
           
            stkRules.StockBalanceFifo(dtStockTable: dtItems, dtLocationTable: dtLocations, fromDate: dtFrom, toDate: dtTo, dispatchType: "", dtStockBalFifo: out dtStockBal);
            // DSPL.Services.Rules.CommonRuleService commonRules = new Services.Rules.CommonRuleService();
            ////decimal curRate =  commonRules.GetLatestCurrencyRate("LKR", "US$", txnDate);
            // commonRules.ValidateUserRights("000", "DSPL");
        }
    }
}
